﻿using LiveCharts;
using LiveCharts.Wpf;
using Sunny.UI;
using SuperMap.Data;
using SuperMap.Realspace;
using SuperMap.UI;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Ycjw.PipeLine.Map.Basic.SuperMap;
using Ycjw.PipeLine.WPF;

namespace Ycjw.PipeLine.BigScreen
{
    public partial class FullScreeFrameworkRealTime : UIForm, IResposeWPF
    {
        /****************************************************************************************/
        /*
        功    能:放置三维场景的DocWindow
        作    者: RenZachary
        联系方式: rzcgis@foxmail.com（QQ455745253）
        生成日期: 2021年3月24日
        修改日志: 
        版权说明: @2021 西安云创经纬信息科技有限公司 版权所有 All right reserved.
        注    意: 本内容仅限于云创经纬公司内部使用，禁止用于商业目的。
        */
        /****************************************************************************************/
        public UIPanel GetCenterPanel()
        {
            return this.uiPanelCenter;
        }
        #region 构造数据
        public void InitData(int tag = 100)
        {
            if (m_FloatWindow == null) return;
            InitData2(tag);
            //InitData3(tag);
        }

        private bool StopTask = false;
        private int TaskFlag = 0;
        private void InitData2(int tag = 100)
        {
            System.Windows.Controls.DataGrid dataGrid = this.m_FloatWindow.DataGridEvents;
            DataTable dt = new DataTable();
            dt.Columns.Add("序号");
            dt.Columns.Add("时间");
            dt.Columns.Add("告警指标");
            dt.Columns.Add("位置");
            for (int i = 0; i < 12; i++)
            {
                DataRow dr = dt.NewRow();
                dr[0] = i + 1;
                dr[1] = DateTime.Now.AddMinutes(0 - i).ToString("MM-dd HH:mm");
                dr[2] = "氯化物(mg/L)";
                dr[3] = "雁塔区翠华路201号";
                dt.Rows.Add(dr);
            }
            dataGrid.ItemsSource = dt.DefaultView;
            dataGrid.LoadingRow += DataGrid_LoadingRow;
            for (int i = 0; i < dataGrid.Columns.Count; i++)
            {
                if (i == 0) dataGrid.Columns[i].Width = 40;
            }
        }

        private void DataGrid_LoadingRow(object sender, System.Windows.Controls.DataGridRowEventArgs e)
        {
            var drv = e.Row.Item as DataRowView;
            
            var index = this.m_FloatWindow.DataGridEvents.Items.IndexOf(drv);
            if (index == 0)
            {
                e.Row.FontWeight = System.Windows.FontWeights.Bold;
            }
            if (index < 3)
            {
                e.Row.Foreground = System.Windows.Media.Brushes.Red;
            }
            else
            {
                e.Row.Foreground = System.Windows.Media.Brushes.White;
                e.Row.FontWeight = System.Windows.FontWeights.ExtraLight;
            }
            if(index %2 == 0)
            {
                e.Row.Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromArgb(102,26,46,60));// System.Windows.Media.Brushes.LightSeaGreen;
            }
            e.Row.VerticalContentAlignment = System.Windows.VerticalAlignment.Center;
        }

        Func<double, string> FormatterT { get; set; }
        Func<double, string> FormatterS { get; set; }
        private void InitData3(int tag = 100)
        {
            for (int i = m_FloatWindow.StackPanel03.Children.Count - 1; i >= 0; i--)
            {
                if (m_FloatWindow.StackPanel03.Children[i] is CartesianChart)
                {
                    m_FloatWindow.StackPanel03.Children.RemoveAt(i);
                }
            }
            CartesianChart cc = new CartesianChart
            {
                LegendLocation = LegendLocation.Right,
                ChartLegend = new DefaultLegend()
                {
                    Foreground = System.Windows.Media.Brushes.White
                }
            };
            m_FloatWindow.StackPanel03.Children.Add(cc);
            //新建一条文件大小的柱状图
            ColumnSeries sizeseries = new ColumnSeries();
            sizeseries.Fill = NewBrush(System.Windows.Media.Colors.Blue);
            //新建一条温度的柱状图
            ColumnSeries templeseries = new ColumnSeries();
            templeseries.Fill = NewBrush(System.Windows.Media.Colors.Yellow);
            //添加两个纵坐标的单位
            FormatterT = value => value + "千米";
            FormatterS = value => value + "平方千米";

            templeseries.Title = "长度";

            //温度的柱状图依赖于第一条纵坐标
            templeseries.ScalesYAt = 0;
            Axis axisT = new Axis { Title = "千米°", LabelFormatter = FormatterT };

            sizeseries.Title = "面积";
            //文件大小的柱状图依赖于第二条纵坐标
            sizeseries.ScalesYAt = 1;
            Axis axisS = new Axis { Title = "平方千米", LabelFormatter = FormatterS };

            cc.AxisY.Add(axisT);
            cc.AxisY.Add(axisS);

            Separator sp = DefaultAxes.CleanSeparator;
            sp.Step = 1;
            cc.AxisX.Add(new Axis()
            {
                Title = "区域",
                Labels = new List<string>() { "莲湖", "雁塔", "长安", "灞桥", "未央", "碑林" },
                LabelsRotation = -45,
                Separator = sp
            });

            List<double> temperature = new List<double>() { 100, 200, 150, 879, 34, 432 };
            for (var t = 0; t < temperature.Count; t++)
            {
                temperature[t] += tag * tag;
            }
            templeseries.Values = new ChartValues<double>(temperature);
            List<double> filesize = new List<double>() { 0.4, 1.5, 8.9, 0.9, 5.5, 10.0 };
            for (var t = 0; t < filesize.Count; t++)
            {
                filesize[t] += tag / 100;
            }
            sizeseries.Values = new ChartValues<double>(filesize);

            var SeriesCollection = new SeriesCollection { };
            SeriesCollection.Add(templeseries);
            SeriesCollection.Add(sizeseries);
            cc.Series.AddRange(SeriesCollection);
        }

        System.Windows.Media.Brush NewBrush(System.Windows.Media.Color color)
        {
            return null;
            /*
            var brush = new System.Windows.Media.SolidColorBrush();
            brush.Color = color;
            brush.Opacity = .3;
            return brush;
            */
        }
        #endregion

        public SceneControl SceneControl { get; set; }
        BFormRealTime m_FloatWindow;
        public FullScreeFrameworkRealTime()
        {
            InitializeComponent();
            this.Width = Screen.PrimaryScreen.Bounds.Width;
            this.Height = Screen.PrimaryScreen.Bounds.Height;
            this.WindowState = FormWindowState.Maximized;
        }
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == Keys.Escape)
                this.Close();
            return base.ProcessCmdKey(ref msg, keyData);
        }
        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);

            if (m_FloatWindow == null) return;
            m_FloatWindow.Width = this.Width;
            m_FloatWindow.Height = this.Height;
        }
        protected override void OnLocationChanged(EventArgs e)
        {
            if (m_FloatWindow == null) return;
            m_FloatWindow.Left = this.Left;
            m_FloatWindow.Top = this.Top;
        }
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            InitChart();

            this.SceneControl.ObjectSelectChanged += SceneControl_ObjectSelectChanged;
            this.SceneControl.MouseUp += SceneControl_MouseUp; ;
            AlertEvents();
        }
        private void SceneControl_MouseUp(object sender, MouseEventArgs e)
        {
            if(this.SceneControl.Scene.FindSelection(true).Length > 0)
            {
                return;
            }

            NameValueCollection hm = new NameValueCollection();
            var trackingLayer = this.SceneControl.Scene.TrackingLayer;
            var index = trackingLayer.HitTest(e.Location);
            if (index < 0)
            {
                this.m_FloatWindow.SetInfo("指标详情", hm);
                return;
            }
            var tag = trackingLayer.GetTag(index);
            var tagArr = tag.Split("_");
            var tagEnd = tagArr[tagArr.Length-1];
            //var txtTag = "ALERT_TEXT_" + tagEnd;

            int indexTarget = 0;
            foreach (var key in AlertText.Keys)
            {
                if(indexTarget + string.Empty == tagEnd)
                {
                    Feature feat = AlertText[key];
                    hm.Add("硫酸盐(mg/L)",feat.GetString("LSY"));
                    hm.Add("氯化物(mg/L)", feat.GetString("LHW"));
                    hm.Add("铁(Fe)(mg/L))", feat.GetString("T"));
                    hm.Add("硝酸盐(以N计)(mg/L)", feat.GetString("XSY"));
                    hm.Add("pH", feat.GetString("PH"));
                    this.m_FloatWindow.SetInfo("指标详情", hm);
                }
                indexTarget++;
            }
        }

        private void SceneControl_ObjectSelectChanged(object sender, ObjectSelectChangedEventArgs e)
        {
            if (this.Visible == false)
            {
                return;
            }
            if (SceneControl.Action != Action3D.Select) return;

            NameValueCollection hm = new NameValueCollection();
            var selection = this.SceneControl.Scene.FindSelection(true);
            var infoName = "信息";
            if (selection.Length == 0)
            {
                this.m_FloatWindow.SetInfo(infoName, hm);
                return;
            }
            var recordset = selection[0].ToRecordset();
            infoName = selection[0].Layer.Caption;
            var fieldInfos = recordset.GetFieldInfos();
            for (int i = 0; i < recordset.FieldCount; i++)
            {
                var caption = fieldInfos[i].Caption;
                var fieldName = fieldInfos[i].Name;
                if (fieldName.ToUpper().StartsWith("SM") && fieldName.ToUpper() != "SMID") continue;
                if (fieldName.ToUpper().StartsWith("SS")) continue;

                var valueObject = recordset.GetFieldValue(fieldName);
                var value = valueObject == null ? string.Empty : valueObject.ToString();
                hm.Add(caption, value);
            }
            this.m_FloatWindow.SetInfo(infoName, hm);
        }

        /// <summary>
        /// 加载透明层
        /// </summary>
        void InitChart()
        {
            m_FloatWindow = new BFormRealTime(this)
            {
                ShowInTaskbar = false,
                Topmost = true,
                Left = this.Left,
                Top = this.Top,
                Width = this.Width,
                Height = this.Height
            };
            m_FloatWindow.Show();
            m_FloatWindow.IsVisibleChanged += FloatWindow_IsVisibleChanged;
            this.SceneControl.Scene.TrackingLayer.IsSelectable = true;
            this.m_FloatWindow.EllipseAll.MouseUp += EllipseAll_MouseUp;
            this.m_FloatWindow.EllipseWS.MouseUp += EllipseWS_MouseUp;
            this.m_FloatWindow.EllipseYS.MouseUp += EllipseYS_MouseUp;

            this.m_FloatWindow.ImageInfo.MouseUp += ImageInfo_MouseUp;
            this.m_FloatWindow.ImagePan.MouseUp += ImagePan_MouseUp;

            this.m_FloatWindow.ImageTerrain.MouseUp += ImageTerrain_MouseUp;
            InitData();
        }

        private void ImageTerrain_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var lyrs = this.SceneControl.Scene.TerrainLayers;
            if (lyrs.Count == 0) return;
            var visible = lyrs[0].IsVisible;
            for (int i = 0; i < lyrs.Count; i++)
            {
                lyrs[i].IsVisible = !visible;
            }
        }

        private void ImagePan_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            SceneControl.Action = Action3D.Pan;
            SceneControl.Scene.Refresh();
        }

        private void ImageInfo_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            SceneControl.Action = SuperMap.UI.Action3D.Select;
            SceneControl.Scene.Refresh();
        }

        private void EllipseYS_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.InitData(30);
        }

        private void EllipseWS_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.InitData(80);
        }

        private void EllipseAll_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.InitData(100);
        }

        private void FloatWindow_IsVisibleChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
        {
            if (m_FloatWindow.IsVisible == false)
            {
                ClearAlertEvents();
                this.Hide();
            }
            else
            {
                this.Show();
                if (this.AlertGeometryTags.Count == 0)
                {
                    AlertEvents();
                }
            }
        }

        public void ResposeWPF(string tag)
        {
            switch (tag)
            {
                case "STOP_CYCLE":
                    break;
                case "VIEWENTIRE":
                    var lookAtKeys = new List<string>()
                    {
                        "Longitude","Latitude","Tilt","Range","Altitude","Heading"
                    };
                    var values = Commons.SerializeHelper.IniHelper.ReadLookAt(lookAtKeys.ToArray());
                    LookAt la = new LookAt()
                    {
                        Longitude = double.Parse(values["Longitude"]),
                        Latitude = double.Parse(values["Latitude"]),
                        Tilt = double.Parse(values["Tilt"]),
                        Range = double.Parse(values["Range"]),
                        Altitude = double.Parse(values["Altitude"]),
                        Heading = double.Parse(values["Heading"])
                    };
                    SceneControl.Scene.Fly(la, 1000);
                    break;
            }
        }
        protected override void OnVisibleChanged(EventArgs e)
        {
            StopTask = !this.Visible;
            TaskFlag = 0;
            base.OnVisibleChanged(e);
            if (m_FloatWindow == null) return;
            if (this.Visible == false)
            {
                m_FloatWindow.Hide();
            }
            else
            {
                m_FloatWindow.Show();
            }
        }

        volatile List<string> AlertGeometryTags = new List<string>();
        volatile List<string> AlertGeometryTagsText = new List<string>();
        volatile Dictionary<Point3D, Feature> AlertText = new Dictionary<Point3D, Feature>();
        static readonly object LockObject = new object();
        private void ClearAlertEvents(bool onlyTxt = false)
        {
            lock (LockObject)
            {
                this.Invoke(new System.Action(() =>
                {
                    var trackingLayer = this.SceneControl.Scene.TrackingLayer;
                    try
                    {
                        for (var i = 0; i < AlertGeometryTags.Count; i++)
                        {
                            var index = trackingLayer.IndexOf(AlertGeometryTags[i]);
                            var index_Text = trackingLayer.IndexOf(AlertGeometryTagsText.Count > i ? AlertGeometryTagsText[i] : string.Empty);

                            if (!onlyTxt && index > -1) trackingLayer.Remove(index);
                            if (index_Text > -1)
                            {
                                Console.WriteLine(AlertGeometryTagsText[i] + "Index-Text：" + index_Text);
                                var removed = trackingLayer.Remove(index_Text);
                                Console.WriteLine("removed : " + removed);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Commons.LogHelper.Error(ex.Message);
                    }
                    if (!onlyTxt)
                    {
                        AlertGeometryTags.Clear();
                    }
                    AlertGeometryTagsText.Clear();
                }));
            }
        }
        private void AlertEvents()
        {
            TaskFlag = 0;
            var dataSource = this.SceneControl.Scene.Workspace.Datasources["WS"];
            var dataSet = dataSource.Datasets["WS_OutPoint"];
            DatasetVectorEx dvEx = new DatasetVectorEx(dataSet.Name)
            {
                DatasetVector = dataSet as DatasetVector
            };
            Task.Factory.StartNew(() => {
                var rst = dvEx.QueryToRecordset("1=1");
                var fs = rst.GetAllFeatures();
                foreach (var k in fs.Keys)
                {
                    var f = fs[k];
                    var g = f.GetGeometry();
                    var point1 = new Point3D(g.InnerPoint.X, g.InnerPoint.Y, 100);
                    AddMarker(point1, point1.X, point1.Y, f);
                }
                while (true)
                {
                    if (this.StopTask)
                    {
                        ClearAlertEvents();
                        AlertGeometryTagsText.Clear();
                        AlertText.Clear();
                        this.Invoke(new System.Action(() => {
                            this.SceneControl.Scene.TrackingLayer.Clear();
                        }));
                        return;
                    }
                    UpdateLabel();
                    Thread.Sleep(1000);
                    TaskFlag++;
                    if (TaskFlag > 10) TaskFlag = 0;
                }
            }).ContinueWith((t) => {
            }, TaskScheduler.FromCurrentSynchronizationContext());
            void UpdateLabel()
            {
                TrackingLayer3D trackingLayer = this.SceneControl.Scene.TrackingLayer;
                ClearAlertEvents(true);
                int index = 0;
                foreach (Point3D txt in AlertText.Keys)
                {
                    Feature feat = AlertText[txt];
                    GeoText3D geoText = new GeoText3D(new TextPart3D(GetText(feat), txt));

                    if (AlertGeometryTagsText.Count == 2)
                    {
                        Styles.SetResultTextStyle(geoText, Color.Red, 4);
                    }
                    else
                    {
                        Styles.SetResultTextStyle(geoText, Color.Green, 4);
                    }
                    geoText.Style3D.AltitudeMode = AltitudeMode.ClampToGround;
                    string tag = "ALERT_TEXT_" + index++;
                    AlertGeometryTagsText.Add(tag);

                    if (AlertGeometryTagsText.Count == 3)
                    {
                        trackingLayer.Add(geoText, tag);
                    }
                }
            }
            void AddMarker(Point3D p3d,double x,double y,Feature feat)
            {
                TrackingLayer3D trackingLayer = this.SceneControl.Scene.TrackingLayer;
                GeoPoint3D gp3d = new GeoPoint3D(p3d);
                double r = 0.0003 * (TaskFlag + 1);
                string markerPath = Commons.Paths.ApplicationResourcesDir + "\\Symbols\\flag01_green.png";
                GeoStyle3D marderStyle = new GeoStyle3D()
                {
                    MarkerFile = markerPath,
                    AltitudeMode = AltitudeMode.ClampToGround
                };
                if (AlertGeometryTagsText.Count == 2)
                {
                    marderStyle.MarkerFile = Commons.Paths.ApplicationResourcesDir + "\\Symbols\\flag01_red.gif";
                }
                Point3D textLocation = gp3d.InnerPoint3D;
                GeoText3D geoText = new GeoText3D(new TextPart3D(GetText(feat), textLocation));
                
                Styles.SetResultTextStyle(geoText, Color.Green, 4);


                geoText.Style3D.AltitudeMode = AltitudeMode.ClampToGround;
                gp3d.Style3D = marderStyle;

                int cnt = AlertGeometryTags.Count;
                Console.WriteLine(" AlertGeometrys.Count : " + cnt);

                AlertGeometryTags.Add("ALERT_" + cnt);
                AlertGeometryTagsText.Add("ALERT_TEXT_" + cnt);

                AlertText.Add(textLocation, feat);

                trackingLayer.Add(gp3d, "ALERT_" + cnt);
                trackingLayer.Add(geoText, "ALERT_TEXT_" + cnt);
            }
        }

        private string GetText(Feature feat)
        {
            var text = string.Empty;
            this.Invoke(new System.Action(() =>
            {
                foreach (var txt in this.m_FloatWindow.ZBNames)
                {
                    if (txt.Name == "AttrLSY" && txt.Text.StartsWith("√"))
                    {
                        text += "硫酸盐(mg/L):" + feat.GetString("LSY") + "\n";
                    }
                    if (txt.Name == "AttrLHW" && txt.Text.StartsWith("√"))
                    {
                        text += "氯化物(mg/L):" + feat.GetString("LHW") + "\n";
                    }
                    if (txt.Name == "AttrT" && txt.Text.StartsWith("√"))
                    {
                        text += "铁(Fe)(mg/L):" + feat.GetString("T") + "\n";
                    }
                    if (txt.Name == "AttrXSY" && txt.Text.StartsWith("√"))
                    {
                        text += "硝酸盐(以N计)(mg/L):" + feat.GetString("XSY") + "\n";
                    }
                    if (txt.Name == "AttrPH" && txt.Text.StartsWith("√"))
                    {
                        text += "pH:" + feat.GetString("PH") + "\n";
                    }
                }
            }));
            return text;
        }

        protected override void OnClosed(EventArgs e)
        {
            if (m_FloatWindow == null) return;
            m_FloatWindow.Hide();
            base.OnClosed(e);
        }
        protected override void Dispose(bool disposing)
        {
            Hide();
        }
    }
}
